//
// Created by 徐套 on 2023/10/1.
//

#include "upper_computer_server.h"




bool upper_computer_server::init_upper_server(){
    start = true;
    std::string init_msg;
    init_msg = "port:" + std::to_string(port_udp) + "!!";
    if (send_msg_by_tcp(init_msg)){
        char recv_msg[1024] = {0};
        recv(client_tcp, recv_msg, sizeof (recv_msg), 0);
        if (recv_msg[0] == '!' && recv_msg[1] == '?' && recv_msg[2] == '!'){
            std::string m = "success!";
            send_msg_by_tcp(m);

            memset(&server_addr_, 0, sizeof(server_addr_));
            server_addr_.sin_family = AF_INET;
            server_addr_.sin_addr.s_addr = inet_addr(upper_ip.c_str());
            server_addr_.sin_port = htons(port_udp);
            server_len_ = sizeof(server_addr_);


            std::thread tcp_thread(&upper_computer_server::tcp_connect, this);
            tcp_thread.detach();
            if (bind(client_udp, (sockaddr*)&server_addr_, sizeof(server_addr_)) != -1) {
                std::thread udp_thread(&upper_computer_server::udp_connect, this);
                udp_thread.detach();
            } else{
                std::string msg = "6:fail to create udp server!";
                send_msg_by_tcp(msg);
            }
            std::thread time_heart(&upper_computer_server::heart_beat_time, this);
            time_heart.detach();

            std::thread send_state(&upper_computer_server::send_car_state, this);
            send_state.detach();
            return true;
        } else
            return false;
    } else
        return false;
}

bool upper_computer_server::send_msg_by_tcp(std::string& msg){
    char m[1024] = {0};
    strcpy(m, msg.c_str());
    if (send(client_tcp, m, strlen(m), 0) != -1){
        return true;
    } else {
        std::cout<<"fail to send msg"<<std::endl;
        return false;
    }
}

void upper_computer_server::send_msg_by_udp(AllCar &car){
    if (start&&udp_start)
        sendto(client_udp, &car, sizeof(car), 0, (struct  sockaddr*)&client_addr_, client_len_);
}

void upper_computer_server::tcp_connect() {
    if(client_tcp != -1){
        std::string msg;
        while (start){
            char read_msg[1024] = {0};
            recv(client_tcp, read_msg, sizeof (read_msg), 0);
            // 信息处理
            if (read_msg[1] == ':'){
                if(read_msg[0] == '3'){
                    // 车辆轨迹信息

                }
                else if(read_msg[0] == '4'){
                    // 心跳包
                    msg = read_msg;
                    time_late = time_->get_now_time() - atoi(&msg[2]);
                    std::cout<<"time out"<<time_late<<std::endl;
                    heart_time = 0;
                }
                else if(read_msg[0] == '7'){
                    // 上位机指令信息
                    car_c->send_msg_by_tcp(read_msg);
                }
            }
        }
    } else
        std::cout<<"fail to create the tcp connect for upper computer"<<std::endl;
}

void upper_computer_server::udp_connect(){
    if (client_udp != -1){
        client_len_ = sizeof(client_addr_);
        char read_msg[1024] = {0};
        recvfrom(client_udp, read_msg, sizeof(read_msg), 0, (struct sockaddr*)&client_addr_, (socklen_t *)&client_len_);
        if (read_msg[0] == '1' && read_msg[1] == '1' && read_msg[2] == '1') {
            udp_start = true;
            std::string ms;
            ms = "6:udp connect";
            send_msg_by_tcp(ms);
        }
        while (start){
            memset(&read_msg, 0, sizeof(read_msg));
            recvfrom(client_udp, read_msg, sizeof(read_msg), 0, (struct sockaddr*)&client_addr_, (socklen_t *)&client_len_);
            // 信息处理

        }
    } else
        std::cout<<"fail to create the udp connect for upper computer"<<std::endl;
}

void upper_computer_server::heart_beat_time() {
    if (client_tcp != -1){
        while (start){
            std::string time_log;
            time_log = "4:" + std::to_string(time_->get_now_time()) + "!end!";
            send_msg_by_tcp(time_log);
            heart_time ++;
            std::string time_late_;
            time_late_ = "8:" + std::to_string(get_time_late()) + "!end!";
            send_msg_by_tcp(time_late_);
            std::this_thread::sleep_for(std::chrono::microseconds(1000));
            if (heart_time > MAXTIMEOUT){
                start = false;
            }
        }
    }
}

unsigned int upper_computer_server::get_time_late() const {
    return time_late;
}

void upper_computer_server::send_car_state() {
    if (client_udp != -1){
        AllCar c;
        while (start){
            memset(&c, 0, sizeof(c));
            if (car_c->have_car_server()) {
                c = car_c->get_all_state();
                send_msg_by_udp(c);
                std::cout << c.all[0].car_name << ":x," << c.all[0].x << ",y:" << c.all[0].y << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds(SENDTIME));
            }
        }
    }
}

bool upper_computer_server::is_alive() const {
    return start;
}
